package cn.yogehaoren.agile_gateway.filter;

import cn.yogehaoren.agile_gateway.entity.ServiceAddress;
import cn.yogehaoren.agile_gateway.util.K8SServiceManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import java.net.URI;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.*;

/**
 * @author WangNing
 * @since 1.0
 */
@Component
@Slf4j
public class K8SDiscoverFilter implements GlobalFilter, Ordered {


    @Autowired
    K8SServiceManager manager;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 获取路径对应的路由
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);

        if(route == null){
            return chain.filter(exchange);
        }
        ServiceAddress serviceAddress;

         serviceAddress = manager.getServiceAddress(route.getId(), route.getUri().toString());

        if(serviceAddress == null){
            return chain.filter(exchange);
        }

        URI uri = exchange.getRequest().getURI();
        boolean encoded = containsEncodedParts(uri);

        ServerHttpRequest req = exchange.getRequest();
        URI mergedUrl = UriComponentsBuilder.fromUri(uri)
                .scheme(serviceAddress.getScheme()).host(serviceAddress.getHost())
                .port(serviceAddress.getPort()).build(encoded).toUri();

        ServerHttpRequest request = req.mutate().uri(mergedUrl).build();
        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
        log.debug("替换请求 {} -> {}", req.getURI().toString(), mergedUrl.toString());

        return chain.filter(exchange.mutate().request(request).build());


    }

    /**
     * 修改路径的优先级必须高于 10000
     * 因为 RouteToRequestUrlFilter 会重新替换 URL
     * @return
     */
    @Override
    public int getOrder() {
        return 10002;
    }
}
